"""
ReAct 工具集 - 心理健康聊天机器人专用工具
"""

import asyncio
import logging
import re
import time
import uuid
from datetime import datetime
from typing import Dict, List, Any, Optional
from abc import ABC, abstractmethod

from app.core.vector_store import get_vector_store
from app.configs.settings import api_settings

logger = logging.getLogger(__name__)


class BaseReActTool(ABC):
    """ReAct 工具基类"""
    
    def __init__(self, name: str, description: str):
        self.name = name
        self.description = description
    
    @abstractmethod
    async def execute(self, action_input: str, react_state: Dict[str, Any]) -> Dict[str, Any]:
        """执行工具操作"""
        pass


class KnowledgeRetrievalTool(BaseReActTool):
    """知识检索工具 - 从向量数据库检索相关心理健康知识"""
    
    def __init__(self):
        super().__init__(
            name="knowledge_retrieval",
            description="检索心理健康相关知识和专业信息，用于回答用户问题"
        )
        self.vector_store = None
    
    async def execute(self, action_input: str, react_state: Dict[str, Any]) -> Dict[str, Any]:
        """执行知识检索"""
        try:
            logger.info(f"[KnowledgeRetrieval] 检索查询: {action_input}")
            
            # 初始化向量存储（如果需要）
            if not self.vector_store:
                try:
                    self.vector_store = get_vector_store()
                except Exception as e:
                    logger.warning(f"[KnowledgeRetrieval] 向量存储初始化失败: {e}")
                    return {
                        "result": "知识库暂时不可用，将基于通用知识回答",
                        "documents": [],
                        "error": True
                    }
            
            # 执行相似性搜索
            try:
                docs = self.vector_store.similarity_search_with_score(action_input, k=3)
                
                if docs:
                    documents = []
                    for doc, score in docs:
                        documents.append({
                            "content": doc.page_content[:500],  # 限制长度
                            "score": float(score),
                            "metadata": doc.metadata
                        })
                    
                    # 格式化检索结果
                    result_text = f"找到 {len(documents)} 个相关文档:\n"
                    for i, doc in enumerate(documents, 1):
                        result_text += f"{i}. {doc['content'][:200]}...\n"
                    
                    return {
                        "result": result_text,
                        "documents": documents,
                        "documents_count": len(documents)
                    }
                else:
                    return {
                        "result": "未找到相关的专业知识，将基于通用心理健康知识回答",
                        "documents": [],
                        "documents_count": 0
                    }
                    
            except Exception as e:
                logger.error(f"[KnowledgeRetrieval] 检索失败: {e}")
                return {
                    "result": f"知识检索出错: {str(e)}",
                    "documents": [],
                    "error": True
                }
                
        except Exception as e:
            logger.error(f"[KnowledgeRetrieval] 工具执行失败: {e}")
            return {
                "result": f"知识检索工具执行失败: {str(e)}",
                "error": True
            }


class EmotionAnalysisTool(BaseReActTool):
    """情感分析工具 - 分析用户的情绪状态"""
    
    def __init__(self):
        super().__init__(
            name="emotion_analysis",
            description="分析用户消息中的情绪状态和心理状态"
        )
        
        # 情绪关键词映射
        self.emotion_keywords = {
            "happy": ["开心", "高兴", "快乐", "愉快", "兴奋", "满足"],
            "sad": ["难过", "伤心", "悲伤", "沮丧", "失落", "痛苦"],
            "angry": ["生气", "愤怒", "恼火", "烦躁", "气愤", "暴躁"],
            "anxious": ["焦虑", "紧张", "担心", "不安", "恐惧", "害怕"],
            "depressed": ["抑郁", "绝望", "无助", "空虚", "麻木", "孤独"],
            "stressed": ["压力", "疲惫", "累", "紧绷", "负担", "重压"]
        }
    
    async def execute(self, action_input: str, react_state: Dict[str, Any]) -> Dict[str, Any]:
        """执行情感分析"""
        try:
            logger.info(f"[EmotionAnalysis] 分析文本: {action_input[:50]}...")

            # 简单的关键词匹配情感分析
            emotion_scores = {}
            text = action_input.lower()

            for emotion, keywords in self.emotion_keywords.items():
                score = 0
                for keyword in keywords:
                    if keyword in text:
                        score += 1
                emotion_scores[emotion] = score

            # 找出最高分的情绪
            if emotion_scores and max(emotion_scores.values()) > 0:
                primary_emotion = max(emotion_scores, key=emotion_scores.get)
                confidence = min(emotion_scores[primary_emotion] / 3.0, 1.0)  # 标准化到0-1
            else:
                primary_emotion = "neutral"
                confidence = 0.5

            # 特殊情况检测
            crisis_indicators = ["自杀", "死", "结束生命", "不想活", "活着没意思"]
            has_crisis = any(indicator in text for indicator in crisis_indicators)

            result = {
                "result": f"检测到主要情绪: {primary_emotion} (置信度: {confidence:.2f})",
                "emotion": primary_emotion,
                "confidence": confidence,
                "emotion_scores": emotion_scores,
                "has_crisis_indicators": has_crisis
            }

            if has_crisis:
                result["crisis_level"] = "high"
                result["requires_immediate_response"] = True
                result["response"] = "我注意到您可能正在经历困难时期。您的生命很宝贵，请不要独自承受。建议您立即联系专业心理健康服务或拨打心理危机干预热线：400-161-9995。"

            # 保存情绪分析结果到数据库
            user_id = react_state.get("user_id")
            if user_id and primary_emotion != "unknown":
                try:
                    from app.services.conversation_service import ConversationService
                    from app.configs.database import get_db

                    # 获取数据库会话
                    db = next(get_db())
                    conversation_service = ConversationService(db)

                    # 保存情绪数据
                    emotion_context = {
                        "message_text": action_input[:100],  # 保存部分消息文本作为上下文
                        "emotion_scores": emotion_scores,
                        "has_crisis": has_crisis,
                        "analysis_method": "keyword_matching"
                    }

                    success = conversation_service.update_user_emotion_profile(
                        user_id=user_id,
                        emotion=primary_emotion,
                        confidence=confidence,
                        emotion_context=emotion_context
                    )

                    if success:
                        logger.info(f"[EmotionAnalysis] 情绪数据已保存到数据库: user_id={user_id}, emotion={primary_emotion}")
                        result["saved_to_database"] = True
                    else:
                        logger.warning(f"[EmotionAnalysis] 情绪数据保存失败: user_id={user_id}")
                        result["saved_to_database"] = False

                except Exception as db_error:
                    logger.error(f"[EmotionAnalysis] 保存情绪数据到数据库失败: {db_error}")
                    result["saved_to_database"] = False
                    result["db_error"] = str(db_error)

            return result

        except Exception as e:
            logger.error(f"[EmotionAnalysis] 分析失败: {e}")
            return {
                "result": f"情感分析失败: {str(e)}",
                "emotion": "unknown",
                "confidence": 0.0,
                "error": True
            }


class SafetyCheckTool(BaseReActTool):
    """安全检查工具 - 检测危机关键词和风险评估"""
    
    def __init__(self):
        super().__init__(
            name="safety_check",
            description="检查用户消息中的安全风险和危机指标"
        )
        
        # 危机关键词
        self.crisis_keywords = [
            "自杀", "死", "结束生命", "不想活", "活着没意思",
            "想死", "去死", "自残", "伤害自己", "了结",
            "绝望", "没有希望", "无法继续", "撑不下去"
        ]
        
        # 风险等级关键词
        self.risk_levels = {
            "high": ["自杀", "死", "结束生命", "想死", "自残"],
            "medium": ["绝望", "没有希望", "撑不下去", "无法继续"],
            "low": ["难过", "沮丧", "压力大", "焦虑"]
        }
    
    async def execute(self, action_input: str, react_state: Dict[str, Any]) -> Dict[str, Any]:
        """执行安全检查"""
        try:
            logger.info(f"[SafetyCheck] 安全检查: {action_input[:50]}...")
            
            text = action_input.lower()
            detected_keywords = []
            risk_level = "low"
            
            # 检测危机关键词
            for keyword in self.crisis_keywords:
                if keyword in text:
                    detected_keywords.append(keyword)
            
            # 评估风险等级
            for level, keywords in self.risk_levels.items():
                for keyword in keywords:
                    if keyword in text:
                        if level == "high":
                            risk_level = "high"
                            break
                        elif level == "medium" and risk_level != "high":
                            risk_level = "medium"
                        elif level == "low" and risk_level not in ["high", "medium"]:
                            risk_level = "low"
            
            # 构建结果
            result = {
                "result": f"安全检查完成，风险等级: {risk_level}",
                "crisis_level": risk_level,
                "detected_keywords": detected_keywords,
                "safety_triggered": len(detected_keywords) > 0
            }
            
            # 高风险情况需要立即响应
            if risk_level == "high":
                result["requires_immediate_response"] = True
                result["response"] = """我非常关心您的安全。如果您正在考虑伤害自己，请立即寻求帮助：

🆘 紧急情况请拨打：120 或 110
📞 心理危机干预热线：400-161-9995
💬 也可以联系当地心理健康服务机构

您的生命很宝贵，困难是暂时的，总有人愿意帮助您。请不要独自承受。"""
            
            return result
            
        except Exception as e:
            logger.error(f"[SafetyCheck] 检查失败: {e}")
            return {
                "result": f"安全检查失败: {str(e)}",
                "crisis_level": "unknown",
                "error": True
            }


class ConversationHistoryTool(BaseReActTool):
    """对话历史工具 - 从向量数据库检索相关历史对话"""

    def __init__(self):
        super().__init__(
            name="conversation_history",
            description="从向量数据库检索相关的历史对话，了解用户的持续关注点和情绪变化"
        )
        self.vector_store = None

    async def execute(self, action_input: str, react_state: Dict[str, Any]) -> Dict[str, Any]:
        """从向量数据库检索相关历史对话"""
        try:
            logger.info(f"[ConversationHistory] 检索相关历史对话")

            # 初始化向量存储（如果需要）
            if not self.vector_store:
                try:
                    self.vector_store = get_vector_store()
                except Exception as e:
                    logger.warning(f"[ConversationHistory] 向量存储初始化失败: {e}")
                    return {
                        "result": "历史对话检索暂时不可用",
                        "conversations": [],
                        "error": True
                    }

            # 获取用户输入作为查询
            user_input = react_state.get("user_input", action_input)

            # 检索相关的历史对话
            try:
                # 只检索对话类型的文档
                docs = self.vector_store.similarity_search_with_score(
                    user_input,
                    k=5,
                    filter={"type": "conversation"}  # 只检索对话记录
                )

                conversations = []
                for doc, score in docs:
                    conversations.append({
                        "content": doc.page_content,
                        "score": float(score),
                        "metadata": doc.metadata
                    })

                # 分析当前对话历史
                chat_history = react_state.get("chat_history", [])

                # 构建当前会话的对话记录
                current_session_conversations = []
                if chat_history:
                    # 将当前会话的对话转换为对话记录格式
                    for i in range(0, len(chat_history) - 1, 2):  # 每两条消息为一组（用户+助手）
                        if i + 1 < len(chat_history):
                            user_msg = chat_history[i]
                            assistant_msg = chat_history[i + 1]

                            if user_msg.get("role") == "human" and assistant_msg.get("role") == "assistant":
                                conversation_content = f"用户: {user_msg.get('content', '')}\n助手: {assistant_msg.get('content', '')}"
                                current_session_conversations.append({
                                    "content": conversation_content,
                                    "score": 0.0,  # 当前会话的相似度设为0（最相关）
                                    "metadata": {
                                        "source": "current_session",
                                        "type": "conversation",
                                        "timestamp": str(int(datetime.now().timestamp())),
                                        "session_index": i // 2
                                    }
                                })

                # 合并当前会话和历史对话记录
                all_conversations = current_session_conversations + conversations

                user_messages = [msg["content"] for msg in chat_history if msg["role"] == "human"]

                # 检测重复主题
                topics = {}
                for msg in user_messages:
                    words = msg.lower().split()
                    for word in words:
                        if len(word) > 2:  # 忽略短词
                            topics[word] = topics.get(word, 0) + 1

                frequent_topics = [topic for topic, count in topics.items() if count > 1]

                patterns = []
                if frequent_topics:
                    patterns.append(f"用户经常提及: {', '.join(frequent_topics[:5])}")
                if len(chat_history) > 5:
                    patterns.append("这是一个较长的对话，用户可能需要深入的支持")
                if conversations:
                    patterns.append(f"找到 {len(conversations)} 个相关的历史对话")

                result = {
                    "result": f"检索到 {len(all_conversations)} 个相关对话记录（包含当前会话 {len(current_session_conversations)} 个对话和历史记录 {len(conversations)} 个对话），当前对话 {len(chat_history)} 条消息",
                    "history_length": len(chat_history),
                    "related_conversations": all_conversations,  # 使用合并后的对话记录
                    "current_session_conversations": current_session_conversations,
                    "historical_conversations": conversations,
                    "patterns": patterns,
                    "frequent_topics": frequent_topics[:5]
                }

                return result

            except Exception as e:
                logger.error(f"[ConversationHistory] 检索失败: {e}")
                return {
                    "result": f"历史对话检索出错: {str(e)}",
                    "conversations": [],
                    "error": True
                }

        except Exception as e:
            logger.error(f"[ConversationHistory] 工具执行失败: {e}")
            return {
                "result": f"对话历史工具执行失败: {str(e)}",
                "error": True
            }


class ConversationStorageTool(BaseReActTool):
    """对话存储工具 - 将对话记录存入向量数据库"""

    def __init__(self):
        super().__init__(
            name="conversation_storage",
            description="将对话记录存入向量数据库，用于后续的上下文检索"
        )
        self.vector_store = None

    async def execute(self, action_input: str, react_state: Dict[str, Any]) -> Dict[str, Any]:
        """存储对话记录到向量数据库"""
        try:
            logger.info(f"[ConversationStorage] 存储对话记录")

            # 初始化向量存储（如果需要）
            if not self.vector_store:
                try:
                    self.vector_store = get_vector_store()
                except Exception as e:
                    logger.warning(f"[ConversationStorage] 向量存储初始化失败: {e}")
                    return {
                        "result": "对话存储暂时不可用",
                        "stored": False,
                        "error": True
                    }

            # 获取对话信息
            user_input = react_state.get("user_input", "")
            ai_response = action_input  # 传入的是AI的回复

            if not user_input or not ai_response:
                return {
                    "result": "缺少用户输入或AI回复，无法存储",
                    "stored": False,
                    "error": True
                }

            # 构建对话记录
            conversation_content = f"用户: {user_input}\n助手: {ai_response}"

            # 获取元数据（向量数据库只支持基本类型）
            tools_used = react_state["metadata"].get("tools_used", [])
            tools_used_str = ",".join(tools_used) if tools_used else "none"

            metadata = {
                "type": "conversation",
                "source": "chat_session",
                "timestamp": str(int(time.time())),
                "user_emotion": react_state["metadata"].get("emotion", "unknown"),
                "crisis_level": react_state["metadata"].get("crisis_level", "low"),
                "tools_used": tools_used_str,  # 转换为字符串
                "conversation_id": react_state.get("conversation_id", "unknown")
            }

            # 生成唯一ID
            conversation_id = f"conv_{int(time.time())}_{uuid.uuid4().hex[:8]}"

            try:
                # 存储到向量数据库
                self.vector_store.add_texts(
                    texts=[conversation_content],
                    metadatas=[metadata],
                    ids=[conversation_id]
                )

                logger.info(f"[ConversationStorage] 对话记录已存储: {conversation_id}")

                return {
                    "result": f"对话记录已成功存储到向量数据库",
                    "stored": True,
                    "conversation_id": conversation_id,
                    "content_length": len(conversation_content)
                }

            except Exception as e:
                logger.error(f"[ConversationStorage] 存储失败: {e}")
                return {
                    "result": f"对话存储失败: {str(e)}",
                    "stored": False,
                    "error": True
                }

        except Exception as e:
            logger.error(f"[ConversationStorage] 工具执行失败: {e}")
            return {
                "result": f"对话存储工具执行失败: {str(e)}",
                "stored": False,
                "error": True
            }


class ProfessionalAdviceTool(BaseReActTool):
    """专业建议工具 - 基于心理学原理生成建议"""
    
    def __init__(self):
        super().__init__(
            name="professional_advice",
            description="基于心理学原理和最佳实践生成专业建议"
        )
        
        # 建议模板
        self.advice_templates = {
            "anxious": [
                "尝试深呼吸练习：4秒吸气，4秒屏息，4秒呼气",
                "使用正念技巧，专注于当下的感受",
                "考虑渐进性肌肉放松练习"
            ],
            "sad": [
                "允许自己感受这些情绪，它们是正常的",
                "尝试与信任的朋友或家人分享感受",
                "考虑参与一些您喜欢的活动"
            ],
            "stressed": [
                "识别压力源并评估哪些是可以控制的",
                "建立健康的边界和优先级",
                "确保充足的睡眠和规律的运动"
            ]
        }
    
    async def execute(self, action_input: str, react_state: Dict[str, Any]) -> Dict[str, Any]:
        """生成专业建议"""
        try:
            logger.info(f"[ProfessionalAdvice] 生成建议: {action_input}")
            
            # 获取情绪状态
            emotion = react_state["metadata"].get("emotion", "unknown")
            crisis_level = react_state["metadata"].get("crisis_level", "low")
            
            advice_list = []
            
            # 基于情绪状态选择建议
            if emotion in self.advice_templates:
                advice_list.extend(self.advice_templates[emotion])
            
            # 通用建议
            general_advice = [
                "保持规律的作息时间",
                "与支持您的人保持联系",
                "如果问题持续，考虑寻求专业心理健康服务"
            ]
            advice_list.extend(general_advice)
            
            # 格式化建议
            formatted_advice = "\n".join([f"• {advice}" for advice in advice_list[:5]])
            
            result = {
                "result": f"基于当前情况生成了 {len(advice_list[:5])} 条专业建议",
                "advice": formatted_advice,
                "advice_count": len(advice_list[:5]),
                "emotion_based": emotion in self.advice_templates
            }
            
            return result
            
        except Exception as e:
            logger.error(f"[ProfessionalAdvice] 生成建议失败: {e}")
            return {
                "result": f"专业建议生成失败: {str(e)}",
                "error": True
            }
